import Taro from '@tarojs/taro';

function isExpired(expires) {
  const expirationDate = new Date(expires);
  const now = new Date();
  return now.getTime() - expirationDate.getTime() >= 0;
}

export function getKey(key: string): string {
  return `${key}_aunt`;
}

const _memory = {};
class Storage {
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  static get memory() {
    return _memory;
  }

  static async getItem(key: string): Promise<null | never> {
    let cachePromise = this.memory[key];
    if (!cachePromise) {
      cachePromise = Taro.getStorage({
        key: getKey(key),
      }).catch(() => {
        this.memory[key] = null;
        return Promise.resolve(null);
      });
      this.memory[key] = cachePromise;
    }
    const res = await cachePromise;

    const storageData = res && res.data;
    if (storageData) {
      if (storageData.expires && isExpired(storageData.expires)) {
        this.removeItem(key);
        return null;
      }
      return storageData.val;
    }
    return null;
  }

  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  static getItemSync(key: string) {
    const res = Taro.getStorageSync(getKey(key));
    const storageData = res && res.data;
    if (storageData) {
      if (storageData.expires && isExpired(storageData.expires)) {
        this.removeItem(key);
        return null;
      }
      return storageData.val;
    }
    return null;
  }

  static setItem(
    key: string,
    val: string,
    expirationDate?: Date
  ): Promise<Taro.General.CallbackResult> {
    if (val !== undefined) {
      const data = {
        expires: expirationDate && expirationDate.toUTCString(),
        val,
      };
      this.memory[key] = null;
      return Taro.setStorage({
        key: getKey(key),
        data,
      });
    }
    return Promise.reject();
  }

  static removeItem(key: string): Promise<Taro.General.CallbackResult> {
    this.memory[key] = null;
    return Taro.removeStorage({
      key: getKey(key),
    });
  }
}

export default Storage;
